{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "538cb9d2",
   "metadata": {
    "origin_pos": 0
   },
   "source": [
    "# Beam Search\n",
    ":label:`sec_beam-search`\n",
    "\n",
    "In :numref:`sec_seq2seq`, \n",
    "we introduced the encoder--decoder architecture,\n",
    "and the standard techniques for training them end-to-end. However, when it came to test-time prediction,\n",
    "we mentioned only the *greedy* strategy,\n",
    "where we select at each time step \n",
    "the token given the highest \n",
    "predicted probability of coming next, \n",
    "until, at some time step, \n",
    "we find that we have predicted\n",
    "the special end-of-sequence \"&lt;eos&gt;\" token.\n",
    "In this section, we will begin \n",
    "by formalizing this *greedy search* strategy\n",
    "and identifying some problems \n",
    "that practitioners tend to run into.\n",
    "Subsequently, we compare this strategy\n",
    "with two alternatives:\n",
    "*exhaustive search* (illustrative but not practical)\n",
    "and *beam search* (the standard method in practice).\n",
    "\n",
    "Let's begin by setting up our mathematical notation,\n",
    "borrowing conventions from :numref:`sec_seq2seq`.\n",
    "At any time step $t'$, the decoder outputs \n",
    "predictions representing the probability \n",
    "of each token in the vocabulary \n",
    "coming next in the sequence \n",
    "(the likely value of $y_{t'+1}$), \n",
    "conditioned on the previous tokens\n",
    "$y_1, \\ldots, y_{t'}$ and \n",
    "the context variable $\\mathbf{c}$,\n",
    "produced by the encoder \n",
    "to represent the input sequence.\n",
    "To quantify computational cost,\n",
    "denote by $\\mathcal{Y}$\n",
    "the output vocabulary \n",
    "(including the special end-of-sequence token \"&lt;eos&gt;\").\n",
    "Let's also specify the maximum number of tokens\n",
    "of an output sequence as $T'$.\n",
    "Our goal is to search for an ideal output from all \n",
    "$\\mathcal{O}(\\left|\\mathcal{Y}\\right|^{T'})$\n",
    "possible output sequences.\n",
    "Note that this slightly overestimates \n",
    "the number of distinct outputs \n",
    "because there are no subsequent tokens\n",
    "once the  \"&lt;eos&gt;\" token occurs.\n",
    "However, for our purposes, \n",
    "this number roughly captures \n",
    "the size of the search space.\n",
    "\n",
    "\n",
    "## Greedy Search\n",
    "\n",
    "Consider the simple *greedy search* strategy from :numref:`sec_seq2seq`.\n",
    "Here, at any time step $t'$, \n",
    "we simply select the token \n",
    "with the highest conditional probability\n",
    "from $\\mathcal{Y}$, i.e., \n",
    "\n",
    "$$y_{t'} = \\operatorname*{argmax}_{y \\in \\mathcal{Y}} P(y \\mid y_1, \\ldots, y_{t'-1}, \\mathbf{c}).$$\n",
    "\n",
    "Once our model outputs \"&lt;eos&gt;\" \n",
    "(or we reach the maximum length $T'$)\n",
    "the output sequence is completed.\n",
    "\n",
    "This strategy might look reasonable, \n",
    "and in fact it is not so bad!\n",
    "Considering how computationally undemanding it is,\n",
    "you'd be hard pressed to get more bang for your buck. \n",
    "However, if we put aside efficiency for a minute,\n",
    "it might seem more reasonable to search \n",
    "for the *most likely sequence*, \n",
    "not the sequence of (greedily selected) *most likely tokens*.\n",
    "It turns out that these two objects can be quite different. \n",
    "The most likely sequence is the one that maximizes the expression\n",
    "$\\prod_{t'=1}^{T'} P(y_{t'} \\mid y_1, \\ldots, y_{t'-1}, \\mathbf{c})$.\n",
    "In our machine translation example,\n",
    "if the decoder truly recovered the probabilities\n",
    "of the underlying generative process, \n",
    "then this would give us the most likely translation.\n",
    "Unfortunately, there is no guarantee \n",
    "that greedy search will give us this sequence.\n",
    "\n",
    "Let's illustrate it with an example.\n",
    "Suppose that there are four tokens \n",
    "\"A\", \"B\", \"C\", and \"&lt;eos&gt;\" in the output dictionary.\n",
    "In :numref:`fig_s2s-prob1`,\n",
    "the four numbers under each time step represent\n",
    "the conditional probabilities of generating \"A\", \"B\", \"C\", \n",
    "and \"&lt;eos&gt;\" respectively, at that time step.\n",
    "\n",
    "![At each time step, greedy search selects the token with the highest conditional probability.](../img/s2s-prob1.svg)\n",
    ":label:`fig_s2s-prob1`\n",
    "\n",
    "At each time step, greedy search selects \n",
    "the token with the highest conditional probability. \n",
    "Therefore, the output sequence \"A\", \"B\", \"C\", and \"&lt;eos&gt;\" \n",
    "will be predicted (:numref:`fig_s2s-prob1`). \n",
    "The conditional probability of this output sequence\n",
    "is $0.5\\times0.4\\times0.4\\times0.6 = 0.048$.\n",
    "\n",
    "\n",
    "Next, let's look at another example in :numref:`fig_s2s-prob2`. \n",
    "Unlike in :numref:`fig_s2s-prob1`, \n",
    "at time step 2 we select the token \"C\", \n",
    "which has the *second* highest conditional probability.\n",
    "\n",
    "![The four numbers under each time step represent \n",
    "the conditional probabilities of generating \"A\", \"B\", \"C\", and \"&lt;eos&gt;\" at that time step. \n",
    "At time step 2, the token \"C\", which has the second highest conditional probability, \n",
    "is selected.](../img/s2s-prob2.svg)\n",
    ":label:`fig_s2s-prob2`\n",
    "\n",
    "Since the output subsequences at time steps 1 and 2, \n",
    "on which time step 3 is based, \n",
    "have changed from \"A\" and \"B\" in :numref:`fig_s2s-prob1` \n",
    "to \"A\" and \"C\" in :numref:`fig_s2s-prob2`, \n",
    "the conditional probability of each token \n",
    "at time step 3 has also changed in :numref:`fig_s2s-prob2`. \n",
    "Suppose that we choose the token \"B\" at time step 3. \n",
    "Now time step 4 is conditional on\n",
    "the output subsequence at the first three time steps\n",
    "\"A\", \"C\", and \"B\", \n",
    "which has changed from \"A\", \"B\", and \"C\" in :numref:`fig_s2s-prob1`. \n",
    "Therefore, the conditional probability of generating \n",
    "each token at time step 4 in :numref:`fig_s2s-prob2` \n",
    "is also different from that in :numref:`fig_s2s-prob1`. \n",
    "As a result, the conditional probability of the output sequence \n",
    "\"A\", \"C\", \"B\", and \"&lt;eos&gt;\" in :numref:`fig_s2s-prob2`\n",
    "is $0.5\\times0.3 \\times0.6\\times0.6=0.054$, \n",
    "which is greater than that of greedy search in :numref:`fig_s2s-prob1`. \n",
    "In this example, the output sequence \"A\", \"B\", \"C\", and \"&lt;eos&gt;\" \n",
    "obtained by the greedy search is not optimal.\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "## Exhaustive Search\n",
    "\n",
    "If the goal is to obtain the most likely sequence, \n",
    "we may consider using *exhaustive search*: \n",
    "enumerate all the possible output sequences \n",
    "with their conditional probabilities,\n",
    "and then output the one that scores \n",
    "the highest predicted probability.\n",
    "\n",
    "\n",
    "While this would certainly give us what we desire,\n",
    "it would come at a prohibitive computational cost \n",
    "of $\\mathcal{O}(\\left|\\mathcal{Y}\\right|^{T'})$,\n",
    "exponential in the sequence length and with an enormous\n",
    "base given by the vocabulary size.\n",
    "For example, when $|\\mathcal{Y}|=10000$ and $T'=10$, \n",
    "both small numbers when compared with ones in real applications, we will need to evaluate $10000^{10} = 10^{40}$ sequences, which is already beyond the capabilities of any foreseeable computers.\n",
    "On the other hand, the computational cost of greedy search is \n",
    "$\\mathcal{O}(\\left|\\mathcal{Y}\\right|T')$: \n",
    "miraculously cheap but far from optimal.\n",
    "For example, when $|\\mathcal{Y}|=10000$ and $T'=10$, \n",
    "we only need to evaluate $10000\\times10=10^5$ sequences.\n",
    "\n",
    "\n",
    "## Beam Search\n",
    "\n",
    "You could view sequence decoding strategies as lying on a spectrum,\n",
    "with *beam search* striking a compromise \n",
    "between the efficiency of greedy search\n",
    "and the optimality of exhaustive search.\n",
    "The most straightforward version of beam search \n",
    "is characterized by a single hyperparameter,\n",
    "the *beam size*, $k$.\n",
    "Let's explain this terminology.\n",
    "At time step 1, we select the $k$ tokens \n",
    "with the highest predicted probabilities.\n",
    "Each of them will be the first token of \n",
    "$k$ candidate output sequences, respectively.\n",
    "At each subsequent time step, \n",
    "based on the $k$ candidate output sequences\n",
    "at the previous time step,\n",
    "we continue to select $k$ candidate output sequences \n",
    "with the highest predicted probabilities \n",
    "from $k\\left|\\mathcal{Y}\\right|$ possible choices.\n",
    "\n",
    "![The process of beam search (beam size $=2$; maximum length of an output sequence $=3$). The candidate output sequences are $\\mathit{A}$, $\\mathit{C}$, $\\mathit{AB}$, $\\mathit{CE}$, $\\mathit{ABD}$, and $\\mathit{CED}$.](../img/beam-search.svg)\n",
    ":label:`fig_beam-search`\n",
    "\n",
    "\n",
    ":numref:`fig_beam-search` demonstrates the \n",
    "process of beam search with an example. \n",
    "Suppose that the output vocabulary\n",
    "contains only five elements: \n",
    "$\\mathcal{Y} = \\{A, B, C, D, E\\}$, \n",
    "where one of them is “&lt;eos&gt;”. \n",
    "Let the beam size be two and \n",
    "the maximum length of an output sequence be three. \n",
    "At time step 1, \n",
    "suppose that the tokens with the highest conditional probabilities \n",
    "$P(y_1 \\mid \\mathbf{c})$ are $A$ and $C$. \n",
    "At time step 2, for all $y_2 \\in \\mathcal{Y},$ \n",
    "we compute \n",
    "\n",
    "$$\\begin{aligned}P(A, y_2 \\mid \\mathbf{c}) = P(A \\mid \\mathbf{c})P(y_2 \\mid A, \\mathbf{c}),\\\\ P(C, y_2 \\mid \\mathbf{c}) = P(C \\mid \\mathbf{c})P(y_2 \\mid C, \\mathbf{c}),\\end{aligned}$$  \n",
    "\n",
    "and pick the largest two among these ten values, say\n",
    "$P(A, B \\mid \\mathbf{c})$ and $P(C, E \\mid \\mathbf{c})$.\n",
    "Then at time step 3, for all $y_3 \\in \\mathcal{Y}$, we compute \n",
    "\n",
    "$$\\begin{aligned}P(A, B, y_3 \\mid \\mathbf{c}) = P(A, B \\mid \\mathbf{c})P(y_3 \\mid A, B, \\mathbf{c}),\\\\P(C, E, y_3 \\mid \\mathbf{c}) = P(C, E \\mid \\mathbf{c})P(y_3 \\mid C, E, \\mathbf{c}),\\end{aligned}$$ \n",
    "\n",
    "and pick the largest two among these ten values, say \n",
    "$P(A, B, D \\mid \\mathbf{c})$   and  $P(C, E, D \\mid  \\mathbf{c}).$\n",
    "As a result, we get six candidates output sequences: \n",
    "(i) $A$; (ii) $C$; (iii) $A$, $B$; (iv) $C$, $E$; (v) $A$, $B$, $D$; and (vi) $C$, $E$, $D$. \n",
    "\n",
    "\n",
    "In the end, we obtain the set of final candidate output sequences \n",
    "based on these six sequences (e.g., discard portions including and after “&lt;eos&gt;”).\n",
    "Then we choose the output sequence which maximizes the following score:\n",
    "\n",
    "$$ \\frac{1}{L^\\alpha} \\log P(y_1, \\ldots, y_{L}\\mid \\mathbf{c}) = \\frac{1}{L^\\alpha} \\sum_{t'=1}^L \\log P(y_{t'} \\mid y_1, \\ldots, y_{t'-1}, \\mathbf{c});$$\n",
    ":eqlabel:`eq_beam-search-score`\n",
    "\n",
    "here $L$ is the length of the final candidate sequence \n",
    "and $\\alpha$ is usually set to 0.75. \n",
    "Since a longer sequence has more logarithmic terms \n",
    "in the summation of :eqref:`eq_beam-search-score`,\n",
    "the term $L^\\alpha$ in the denominator penalizes\n",
    "long sequences.\n",
    "\n",
    "The computational cost of beam search is $\\mathcal{O}(k\\left|\\mathcal{Y}\\right|T')$. \n",
    "This result is in between that of greedy search and that of exhaustive search.\n",
    "Greedy search can be treated as a special case of beam search \n",
    "arising when the beam size is set to 1.\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "## Summary\n",
    "\n",
    "Sequence searching strategies include \n",
    "greedy search, exhaustive search, and beam search.\n",
    "Beam search provides a trade-off between accuracy and \n",
    "computational cost via the flexible choice of the beam size.\n",
    "\n",
    "\n",
    "## Exercises\n",
    "\n",
    "1. Can we treat exhaustive search as a special type of beam search? Why or why not?\n",
    "1. Apply beam search in the machine translation problem in :numref:`sec_seq2seq`. How does the beam size affect the translation results and the prediction speed?\n",
    "1. We used language modeling for generating text following  user-provided prefixes in :numref:`sec_rnn-scratch`. Which kind of search strategy does it use? Can you improve it?\n",
    "\n",
    "[Discussions](https://discuss.d2l.ai/t/338)\n"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  },
  "required_libs": []
 },
 "nbformat": 4,
 "nbformat_minor": 5
}